home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / M / MacPerl 4.13 source.sit / Perl Source ƒ / MacPerl / MPFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-27  |  16.3 KB  |  780 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPFile.c            -
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPFile.c,v $
  12. Revision 1.1  1994/02/27  23:00:47  neeri
  13. Initial revision
  14.  
  15. Revision 0.6  1993/09/17  00:00:00  neeri
  16. Runtime version
  17.  
  18. Revision 0.5  1993/08/28  00:00:00  neeri
  19. Handle multiple preference files
  20.  
  21. Revision 0.4  1993/08/17  00:00:00  neeri
  22. Enable Save
  23.  
  24. Revision 0.3  1993/08/13  00:00:00  neeri
  25. Write bounds rectangles
  26.  
  27. Revision 0.2  1993/05/30  00:00:00  neeri
  28. Support Console Windows
  29.  
  30. Revision 0.1  1993/05/29  00:00:00  neeri
  31. Compiles correctly
  32.  
  33. *********************************************************************/
  34.  
  35. #include <Errors.h>
  36. #include <Resources.h>
  37. #include <Desk.h>
  38. #include <PLStringFuncs.h>
  39. #include <AppleEvents.h>
  40. #include <AERegistry.h>
  41. #include <StandardFile.h>
  42. #include <TFileSpec.h>
  43.  
  44. #include "MPFile.h"
  45. #include "MPSave.h"
  46.  
  47. /**-----------------------------------------------------------------------
  48.         Name:             FileError
  49.         Purpose:        Puts up an error alert.
  50.     -----------------------------------------------------------------------**/
  51.  
  52.  
  53. #pragma segment File
  54.  
  55. pascal void FileError(Str255 s, Str255 f)
  56. {
  57.     short    alertResult;
  58.  
  59.     SetCursor(&qd.arrow);
  60.     ParamText(s, f, "", "");
  61.      alertResult = Alert(ErrorAlert, nil);
  62. }
  63.  
  64. /**-----------------------------------------------------------------------
  65.         Name:             DoClose
  66.         Purpose:        Closes a window.
  67.     -----------------------------------------------------------------------**/
  68.  
  69. #pragma segment File
  70.  
  71. pascal OSErr DoClose(WindowPtr aWindow, Boolean canInteract, DescType dialogAnswer)
  72. {
  73.      DPtr    aDocument;
  74.      short   alertResult;
  75.      Str255  theName;
  76.     OSErr   myErr;
  77.  
  78.     myErr = noErr;
  79.  
  80.      if (gWCount > 0) {
  81.         aDocument = DPtrFromWindowPtr(aWindow);
  82.  
  83.         if (aDocument->kind == kDocumentWindow) {
  84.             if (aDocument->dirty)
  85.                 if (canInteract && (dialogAnswer==kAEAsk)) {
  86.                     if (aDocument->u.reg.everSaved == false)
  87.                         GetWTitle(aWindow, theName); /* Pick it up as a script may have changed it */
  88.                     else
  89.                         PLstrcpy(theName, aDocument->theFileName);
  90.     
  91.                     ParamText(theName, "", "", "");
  92.                     SetCursor(&qd.arrow);
  93.                     alertResult = Alert(SaveAlert, nil);
  94.                     switch (alertResult) {
  95.                     case aaSave:
  96.                         myErr = SaveAskingName(aDocument, canInteract);
  97.                         break;
  98.     
  99.                     case aaCancel:
  100.                         return userCanceledErr;
  101.     
  102.                     case aaDiscard:
  103.                         aDocument->dirty = false;
  104.                         break;
  105.                     }
  106.                 } else {
  107.                     if (dialogAnswer==kAEYes)
  108.                         myErr = SaveAskingName(aDocument, canInteract);
  109.                     else
  110.                         myErr = noErr; /* Don't save */
  111.                 }
  112.                 
  113.             if (!myErr) {
  114. #ifndef RUNTIME
  115.                 if (aDocument->kind == kDocumentWindow && aDocument->u.reg.numSections)
  116.                     DeRegisterAllSections(aDocument);
  117. #endif
  118.  
  119.                 CloseMyWindow(aWindow);
  120.             }
  121.         } else if (aDocument->u.cons.selected) {
  122.             if (!gQuitting) {
  123.                 SysBeep(0);
  124.     
  125.                 return userCanceledErr;
  126.             }
  127.         } else 
  128.             SaveConsole(aDocument);
  129.     } else
  130.         myErr = errAEIllegalIndex;
  131.  
  132.     return myErr;
  133. }
  134.  
  135. #pragma segment File
  136.  
  137. //  DoQuit
  138. //  saveOpt - one of kAEAsk,kAEYes,kAENo
  139. //  if kAEYes or kAEAsk then AEInteactWithUser should have been called
  140. //  before DoQuit. Assumes that it can interact if it needs to.
  141.  
  142. pascal void DoQuit(DescType saveOpt)
  143. {
  144.     WindowPeek    aWindow;
  145.     WindowPeek    nextWindow;
  146.     short            theKind;
  147.  
  148.     if (gRunningPerl && (Alert(AbortAlert, nil) == 2))
  149.         return;
  150.         
  151.     gQuitting = true;
  152.  
  153.     for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
  154.         nextWindow = aWindow->nextWindow;
  155.         if (Ours((WindowPtr) aWindow)) {
  156.             if (DoClose((WindowPtr) aWindow, true, saveOpt)) {
  157.                 gQuitting = false;
  158.                 
  159.                 return;
  160.             }
  161.         } else {
  162.             theKind = aWindow->windowKind;
  163.             if (theKind < 0)
  164.                 CloseDeskAcc(theKind);
  165.         }
  166.     }
  167. }
  168.  
  169. pascal Boolean GetFileFilter(ParmBlkPtr info)
  170. {
  171.     switch (info->fileParam.ioFlFndrInfo.fdType) {
  172.     case 'APPL':
  173.         switch (info->fileParam.ioFlFndrInfo.fdCreator) {
  174.         case MPRtSig:
  175.             return false;
  176.         case MPAppSig:
  177.             return !info->fileParam.ioFlLgLen;
  178.         default:
  179.             return true;
  180.         }
  181.     case 'TEXT':
  182.         return false;
  183.     default:
  184.         return true;
  185.     }
  186. }
  187.  
  188. pascal OSErr GetFile(FSSpec *theFSSpec)
  189. {
  190. #ifndef RUNTIME
  191.  
  192.     SFTypeList         myTypes = {'TEXT', 'APPL'};
  193.     StandardFileReply  reply;
  194.  
  195.     StandardGetFile(GetFileFilter, 2, myTypes, &reply);
  196.  
  197.     if (reply.sfGood) {
  198.         *theFSSpec = reply.sfFile;
  199.         return noErr;
  200.     } else
  201.         return userCanceledErr;
  202.         
  203. #else
  204.  
  205.     SFTypeList     myTypes = {'TEXT', 'APPL'};
  206.     SFReply          reply;
  207.     Point            where;
  208.  
  209.     where.h = where.v = 75;
  210.  
  211.     SFGetFile(
  212.         where, "\p", 
  213.         GetFileFilter, 2, myTypes, 
  214.         (DlgHookProcPtr) nil,
  215.         &reply);
  216.  
  217.     if (reply.good)
  218.         return WD2FSSpec(reply.vRefNum, reply.fName, theFSSpec);
  219.     else
  220.         return userCanceledErr;
  221.         
  222. #endif
  223. }
  224.  
  225. #pragma segment File
  226.  
  227. pascal OSErr DoCreate(FSSpec theSpec)
  228. {
  229.     OSErr err;
  230.  
  231. #ifndef RUNTIME
  232.     err = FSpCreate(&theSpec, MPAppSig, 'TEXT', smSystemScript);
  233. #else
  234.     err = HCreate(theSpec.vRefNum, theSpec.parID, theSpec.name, MPAppSig, 'TEXT');
  235. #endif
  236.  
  237.     if (!err)
  238.         HCreateResFile(theSpec.vRefNum, theSpec.parID, theSpec.name);
  239.     else
  240.         ShowError("\pCreating", err);
  241.  
  242.     return err;
  243. }
  244.  
  245. pascal OSErr SaveConsole(DPtr doc)
  246. {
  247.     OSErr            err;
  248.     short       resFile;
  249.     HHandle     theHHandle;
  250.     Str255        title;
  251.     Boolean        existing;
  252.     
  253.     if (gPrefsFile) {
  254.         resFile    =    CurResFile();
  255.         UseResFile(gPrefsFile);
  256.         GetWTitle(doc->theWindow, title);
  257.         
  258.         if (theHHandle = (HHandle) Get1NamedResource('TFSS', title)) {
  259.             existing = true;
  260.         } else {
  261.             existing = false;
  262.             theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  263.         }
  264.         
  265.         HLock((Handle)theHHandle);
  266.     
  267.         (*theHHandle)->theRect     = doc->theWindow->portRect;
  268.         OffsetRect(
  269.             &(*theHHandle)->theRect,
  270.             -doc->theWindow->portBits.bounds.left,
  271.             -doc->theWindow->portBits.bounds.top);
  272.             
  273.         GetFontName((*(doc->theText))->txFont, &(*theHHandle)->theFont);
  274.         
  275.         (*theHHandle)->theSize     = (*(doc->theText))->txSize;
  276.         (*theHHandle)->lastID      = 0;
  277.         (*theHHandle)->numSections = 0;
  278.     
  279.         HUnlock((Handle)theHHandle);
  280.     
  281.         if (existing) {
  282.             ChangedResource((Handle) theHHandle);
  283.             WriteResource((Handle) theHHandle);
  284.             UpdateResFile(gPrefsFile);
  285.         } else {
  286.             AddResource((Handle)theHHandle, 'TFSS', Unique1ID('TFSS'), title);
  287.         }
  288.         
  289.         err = ResError();
  290.         
  291.         UseResFile(resFile);
  292.     }
  293.     
  294.     DoHideWindow(doc->theWindow);
  295.     TESetSelect(0, 32767, doc->theText);
  296.     TEDelete(doc->theText);
  297.     
  298.     if (doc->u.cons.fence < 32767)
  299.         doc->u.cons.fence    = 0;
  300.     
  301.     return err;
  302.  
  303. pascal void ApplySettings(DPtr doc, HPtr settings)
  304. {
  305.     short        fNum;
  306.     FontInfo    info;
  307.     Rect        bounds;
  308.     
  309.     GetFNum(settings->theFont, &fNum);
  310.     SetPort(doc->theWindow);
  311.     TextFont(fNum);
  312.     TextSize(settings->theSize);
  313.     GetFontInfo(&info);
  314.     
  315.     (*doc->theText)->txFont         = fNum;
  316.     (*doc->theText)->txSize         = settings->theSize;
  317.     (*doc->theText)->lineHeight    = info.ascent+info.descent+info.leading;
  318.     (*doc->theText)->fontAscent    = info.ascent;
  319.     
  320.     bounds                                = settings->theRect;
  321.     InsetRect(&bounds, 20, 20);
  322.     
  323.     if (settings->theRect.right > settings->theRect.left + 50 &&
  324.         settings->theRect.bottom > settings->theRect.top  + 50 &&
  325.         RectInRgn(&bounds, GetGrayRgn())
  326.     ) {
  327.         MoveWindow(doc->theWindow, settings->theRect.left, settings->theRect.top, false);
  328.         SizeWindow(
  329.             doc->theWindow,
  330.             settings->theRect.right - settings->theRect.left,
  331.             settings->theRect.bottom - settings->theRect.top,
  332.             false);
  333.     }
  334.         
  335.     ResizeWindow(doc);
  336. }
  337.  
  338. pascal void RestoreConsole(DPtr doc)
  339. {
  340.     short       resFile;
  341.     HHandle     theHHandle;
  342.     Str255        title;
  343.     
  344.     if (!gPrefsFile)
  345.         return;
  346.         
  347.     resFile    =    CurResFile();
  348.     UseResFile(gPrefsFile);
  349.     GetWTitle(doc->theWindow, title);
  350.     
  351.     if (theHHandle = (HHandle) Get1NamedResource('TFSS', title)) {
  352.          HLock((Handle)theHHandle);
  353.         
  354.         ApplySettings(doc, *theHHandle);
  355.         
  356.         HUnlock((Handle)theHHandle);
  357.     }
  358.     
  359.     UseResFile(resFile);
  360. }
  361.  
  362.  
  363. /** -----------------------------------------------------------------------
  364.         Name:         GetFileContents
  365.         Purpose:        Opens the document specified by theFSSpec and puts
  366.                         the contents into theDocument.
  367.      -----------------------------------------------------------------------**/
  368.  
  369. #pragma segment File
  370.  
  371. pascal OSErr GetFileContents(FSSpec spec, DPtr theDocument)
  372. {
  373.     long            theSize;
  374.     short            oldRes;
  375.     short            resFile;
  376.     short            refNum;
  377.     OSErr            err;
  378.     HHandle        aHandle;
  379.     Handle        gHandle;
  380.  
  381.     oldRes    =    CurResFile();
  382.     resFile     =    HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
  383.  
  384.     switch (theDocument->type) {
  385.     case kOldRuntime6Doc:
  386.     case kPlainTextDoc:
  387. #ifndef RUNTIME
  388.         if (err = HOpenDF(spec.vRefNum, spec.parID, spec.name, fsRdPerm, &refNum)) {
  389.             ShowError("\pread file - HOpenDF", err);
  390. #else
  391.         if (err = HOpen(spec.vRefNum, spec.parID, spec.name, fsRdPerm, &refNum)) {
  392.             ShowError("\pread file - HOpen", err);
  393. #endif
  394.             refNum = 0;
  395.             
  396.             goto giveUp;
  397.         }
  398.     
  399.         if (err = GetEOF(refNum, &theSize))
  400.             goto giveUp;
  401.  
  402.           gHandle = NewHandle(theSize);
  403.  
  404.         HLock(gHandle);
  405.         if (err = FSRead(refNum, &theSize, *gHandle))
  406.             return err;
  407.         HUnlock(gHandle);
  408.         FSClose(refNum);
  409.         break;
  410.         
  411. giveUp:    
  412.         if (refNum)
  413.             FSClose(refNum);
  414.             
  415.         if (resFile > -1)
  416.             CloseResFile(resFile);
  417.         
  418.         UseResFile(oldRes);
  419.         
  420.         return err;
  421.     default:
  422.         gHandle    =    Get1NamedResource('TEXT', "\p!");
  423.         
  424.         if (gHandle) 
  425.             DetachResource(gHandle);
  426.         else {
  427.             err = ResError();
  428.             
  429.             goto giveUp;
  430.         }
  431.         break;
  432.     }
  433.  
  434.     theDocument->u.reg.numSections = 0;
  435.  
  436.     if (resFile != -1) {
  437.         aHandle = nil;
  438.  
  439.         if (Count1Resources('TFSS'))
  440.             aHandle = (HHandle)Get1Resource('TFSS', 255);
  441.  
  442.         if (aHandle) {
  443.             theDocument->u.reg.numSections = (*aHandle)->numSections;
  444.             
  445.             HLock((Handle) aHandle);
  446.             ApplySettings(theDocument, *aHandle);
  447.         }
  448.  
  449.         /*
  450.             If there is a print record saved, ditch the old one
  451.             created by new document and fill this one in
  452.         */
  453.         if (Count1Resources('TFSP')) {
  454.             if (theDocument->thePrintSetup)
  455.                 DisposHandle((Handle)theDocument->thePrintSetup);
  456.  
  457.             theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255);
  458.               HandToHand((Handle *)&theDocument->thePrintSetup);
  459.  
  460.             PrValidate(theDocument->thePrintSetup);
  461.         }
  462.  
  463. #ifndef RUNTIME
  464.         if (theDocument->u.reg.numSections) {
  465.             ReadSectionRecords(theDocument);
  466.             ReadAllSectionResources(theDocument);
  467.         }
  468. #else
  469.         theDocument->u.reg.numSections    =    0;
  470. #endif
  471.  
  472.         CloseResFile(resFile);
  473.  
  474.         if (err = ResError()) {
  475.             ShowError("\pread file- CloseResFile", err);
  476.             return err;
  477.         }
  478.     }
  479.  
  480.     HLock(gHandle);
  481.     if (GetHandleSize(gHandle) > 32000) {
  482.         PtrToXHand(
  483.             *gHandle, 
  484.             (*theDocument->theText)->hText, 
  485.             GetHandleSize(gHandle));
  486.         
  487.         err = elvisErr;
  488.     } else
  489.         TESetText(*gHandle, GetHandleSize(gHandle), theDocument->theText);
  490.     DisposHandle(gHandle);
  491.  
  492.     if (err == fnfErr)
  493.         return noErr;
  494.     else
  495.           return err;
  496. } /* GetFileContents */
  497.  
  498.  
  499. #pragma segment File
  500.  
  501. pascal OSErr SaveAskingName(DPtr aDocument, Boolean canInteract)
  502. {
  503.     OSErr    myErr;
  504.  
  505.     if (aDocument->kind != kDocumentWindow || !aDocument->u.reg.everSaved) {
  506.  
  507.         if (canInteract) {
  508.             if (myErr = GetFileNameToSaveAs(aDocument))
  509.                 return myErr;
  510.  
  511.             if (myErr = DoSave(aDocument, aDocument->theFSSpec))
  512.                 return myErr;
  513.  
  514. #ifndef RUNTIME
  515.             AssocAllSections(aDocument);
  516. #endif
  517.  
  518.             return noErr;
  519.         } else
  520.             return errAENoUserInteraction;
  521.  
  522.     } else
  523.         return SaveUsingTemp(aDocument);
  524. }
  525.  
  526. #pragma segment File
  527.  
  528. pascal OSErr SaveUsingTemp(DPtr theDocument)
  529. {
  530.     Str255    tempName;
  531.     OSErr        err;
  532.     FSSpec    tempFSSpec;
  533.  
  534.     /*save the file to disk using a temporary file*/
  535.     /*this is the recommended way of doing things*/
  536.     /*first write out the file to disk using a temporary filename*/
  537.     /*if it is sucessfully written, exchange the temporary file with the last one saved*/
  538.     /*then delete the temporary file- so if anything goes wrong, the original version is still there*/
  539.     /*first generate the temporary filename*/
  540.  
  541.     GetTempFileName(theDocument, &tempName);
  542.     /*create this file on disk*/
  543.  
  544.     tempFSSpec = theDocument->theFSSpec;
  545.     PLstrcpy(tempFSSpec.name, tempName);
  546.  
  547.     if (err = DoCreate(tempFSSpec))
  548.         return err;
  549.  
  550.     if (err = DoSave(theDocument, tempFSSpec))
  551.         return err;
  552.     
  553. #ifndef RUNTIME
  554.     if (err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec))
  555.         return err;
  556.  
  557.     /*we've exchanged the files, now delete the temporary one*/
  558.  
  559.     err = FSpDelete(&tempFSSpec);
  560. #else
  561.     err = FSpSmartMove(&tempFSSpec, &theDocument->theFSSpec);
  562. #endif
  563.     
  564.     if (!err)
  565.         theDocument->dirty = false;
  566.  
  567.     return err;
  568. }
  569.  
  570.  
  571. #pragma segment File
  572.  
  573. pascal short SaveScriptHook(short item, DialogPtr dlg, void * params)
  574. {
  575.     short                kind;
  576.     ControlHandle    type;
  577.     Rect                r;
  578.     DPtr                doc = (DPtr) params;
  579.     
  580.     if (GetWRefCon(dlg) != 'stdf')
  581.         return item;
  582.         
  583.     switch (item) {
  584.     case sfHookFirstCall:
  585.         GetDItem(dlg, ssd_Type, &kind, (Handle *) &type, &r);
  586.         SetCtlValue(type, doc->type);
  587.         
  588.         return sfHookFirstCall;
  589.     case ssd_Type:
  590.         GetDItem(dlg, item, &kind, (Handle *) &type, &r);
  591.         
  592.         doc->type = (DocType) GetCtlValue(type);
  593.         
  594.         return sfHookNullEvent;
  595.     default:
  596.         return item;
  597.     }
  598. }
  599.  
  600. /*
  601.     Fills in the document record with the user chosen destination
  602. */
  603.  
  604. pascal OSErr GetFileNameToSaveAs(DPtr theDocument)
  605. {
  606. #ifndef RUNTIME
  607.     OSErr                    err;
  608.     StandardFileReply    reply;
  609.     Str255            suggestName;
  610.     Point                    where;
  611.     
  612.     where.h = where.v = -1;
  613.  
  614.     GetWTitle(theDocument->theWindow, suggestName);
  615.  
  616.     CustomPutFile(
  617.         "\pSave Document As:", suggestName, &reply,
  618.         SaveScriptDialog,
  619.         where,
  620.         SaveScriptHook,
  621.         (ModalFilterYDProcPtr) nil,
  622.         nil,
  623.         (ActivateYDProcPtr) nil,
  624.         theDocument);
  625.  
  626.     if (reply.sfGood)
  627.         switch (err = FSpDelete(&reply.sfFile)) {
  628.         case noErr:
  629.         case fnfErr:
  630.             theDocument->theFSSpec = reply.sfFile;
  631.             PLstrcpy(theDocument->theFileName, reply.sfFile.name);
  632.  
  633.             return noErr;
  634.         default:
  635.             return err;
  636.         }
  637.     else
  638.         return userCanceledErr;
  639. #else
  640.     OSErr        err;
  641.     SFReply    reply;
  642.     Str255   suggestName;
  643.     Point        where;
  644.  
  645.     where.h = where.v = 75;
  646.     
  647.     GetWTitle(theDocument->theWindow, suggestName);
  648.  
  649.     SFPutFile(
  650.         where, "\pSave Document As:", 
  651.         suggestName, (DlgHookProcPtr) nil,
  652.         &reply);
  653.     
  654.     if (reply.good) {
  655.         FSSpec    spec;
  656.         
  657.         if (err = WD2FSSpec(reply.vRefNum, reply.fName, &spec))
  658.             return err;
  659.         switch (err = HDelete(spec.vRefNum, spec.parID, spec.name)) {
  660.         case noErr:
  661.         case fnfErr:
  662.             theDocument->theFSSpec = spec;
  663.             PLstrcpy(theDocument->theFileName, spec.name);
  664.  
  665.             return noErr;
  666.         default:
  667.             return err;
  668.         }
  669.     } else
  670.         return userCanceledErr;
  671. #endif
  672. } /* GetFileNameToSaveAs */
  673.  
  674. #pragma segment File
  675.  
  676. pascal OSErr OpenOld(FSSpec aFSSpec, DocType type)
  677. {
  678.     DPtr          theDocument;
  679.     OSErr         fileErr;
  680.     
  681.     theDocument = NewDocument(true, kDocumentWindow);
  682.  
  683.     SetWTitle(theDocument->theWindow, aFSSpec.name);
  684.  
  685.     SetPort(theDocument->theWindow);
  686.  
  687.     theDocument->theFSSpec   = aFSSpec;
  688.  
  689.     PLstrcpy(theDocument->theFileName,aFSSpec.name);
  690.  
  691.     theDocument->dirty               = false;
  692. #ifndef RUNTIME
  693.     theDocument->type                    = (type == kOldRuntime6Doc) ? kRuntime6Doc : type;
  694.     theDocument->u.reg.everSaved    = (type != kOldRuntime6Doc);
  695. #else
  696.     theDocument->type                    = kPlainTextDoc;
  697.     theDocument->u.reg.everSaved    = (type == kPlainTextDoc);
  698. #endif
  699.  
  700.     fileErr = GetFileContents(aFSSpec, theDocument);
  701.  
  702.     if (!fileErr) {
  703.         ResizeWindow(theDocument);
  704.         DoShowWindow(theDocument->theWindow);
  705.     } else {
  706.         if (fileErr == elvisErr) {
  707.             theDocument->u.reg.everSaved    = false;
  708. #ifdef RUNTIME
  709.             if (AEInteractWithUser(kAEDefaultTimeout, nil, nil))
  710. #endif
  711.                 if (Alert(ElvisAlert, nil) == 1)
  712.                     SaveAskingName(theDocument, true);
  713.         } else
  714.             FileError("\pError Opening ", aFSSpec.name);
  715.         
  716.         CloseMyWindow(theDocument->theWindow);
  717.     }
  718.  
  719.     return fileErr;
  720. } /* OpenOld */
  721.  
  722. pascal DocType GetDocType(FSSpec * spec)
  723. {
  724.     CInfoPBRec    info;
  725.     DocType        type    =    kUnknownDoc;
  726.     short            resFile;
  727.     short            nuFile;
  728.     OSType    **    rtType;
  729.  
  730.     if (FSpCatInfo(spec, &info))
  731.         return kUnknownDoc;
  732.     
  733.     switch (info.hFileInfo.ioFlFndrInfo.fdType) {
  734.     case 'APPL':
  735.         switch (info.hFileInfo.ioFlFndrInfo.fdCreator) {
  736.         case MPRtSig:
  737.             resFile    =    CurResFile();
  738.             nuFile    =    HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdPerm);
  739.             
  740.             if (nuFile != -1) {
  741.                 if (rtType = (OSType **) Get1Resource('MrPL', 128))
  742.                     switch (**rtType) {
  743.                     case 'SCPT':
  744.                         type        =    kScriptDoc;
  745.                         break;
  746.                     case 'MrP7':
  747.                         type        =    kRuntime7Doc;
  748.                         break;
  749.                     case 'MrP6':
  750.                         type         =    kRuntime6Doc;
  751.                         break;
  752.                     }
  753.                     
  754.                 CloseResFile(nuFile);
  755.             }
  756.             UseResFile(resFile);
  757.             
  758.             return type;
  759.         case MPAppSig:
  760.             /* A heuristic to separate old runtimes from PowerPC executables */
  761.             if (info.hFileInfo.ioFlLgLen && info.hFileInfo.ioFlLgLen < 100000)
  762.                 return kOldRuntime6Doc; 
  763.             /* Fall through */
  764.         default:
  765.             return kUnknownDoc;
  766.         }
  767.     case 'TEXT':
  768.         return kPlainTextDoc;
  769.     case 'pref':
  770.         switch (info.hFileInfo.ioFlFndrInfo.fdCreator) {
  771.         case MPAppSig:
  772.         case MPRtSig:
  773.             return kPreferenceDoc;
  774.         }
  775.         /* Fall through */
  776.     default:
  777.         return kUnknownDoc;
  778.     }
  779. }